import sys
import getopt
from time import *
from socket import *
from struct import *

class tablet_server:
    address = None
    sock = None

class tablet:
    tablet_id = None
    table_name = None
    start_row = None
    end_row = None
    status = None
    server = tablet_server()
    
class server_address:
    host_name = None
    port = None
    start_code = None

def unpack_string(buf,offset):
    str_len = unpack_from('!I',buf,offset)
    offset += calcsize("!I")
    
    str = unpack_from(str(str_len)+'s',buf,offset)
    
    return str,(calcsize("!I")+str_len)

def unpack_tablet(buf,offset):
    root_tablet = tablet()
    
    root_tablet.tablet_id = unpack_from('L!',buf,offset)
    offset += calcsize('L!')
    
    root_tablet.table_name,decode_len = unpack_string(buf,offset)
    offset += decode_len
    
    root_tablet.start_row,decode_len = unpack_string(buf,offset)
    offset += decode_len
    
    root_tablet.end_row,decode_len = unpack_string(buf,offset)
    offset += decode_len
    
    root_tablet.status = unpack_from('S!',buf)
    offset += calcsize('S!')
    
    return root_tablet

def unpack_server_address(buf,offset):
    server_address_obj = server_address()

    server_address_obj.host_name,decode_len = unpack_string(buf,offset)
    offset += decode_len
    
    server_address_obj.port = unpack_from('H!',buf,offset)
    offset += calcsize('H!')
    
    server_address_obj.start_code = unpack_from('L!',buf,offset)
    offset += calcsize('L!')
    
    return server_address_obj

def send_packet(sock, pkt_buf, pkt_type, pkt_seq):
    buf = ''
    
    # magic
    buf += pack('H!',0x11DE)
    # version
    buf += pack('B!',1)
    # type
    buf += pack('H!',pkt_type)
    # seq
    buf += pack('I!',pkt_seq)
    # length
    buf += pack('I!',len(pkt_buf))
    # packet
    buf += pack('s',pkt_buf)
    
def tablet_scan_open(tablet):
    pass

def tablet_scan_next(tablet):
    pass

def tablet_scan(tablet,start_row,end_row):
    pass

def get_table_meta_data(root_tablet,table_name):
    root_tablet.server.sock = socket(AF_INET, SOCK_STREAM)
    try:
        root_tablet.server.sock.connect((root_tablet.address.host_name,root_tablet.address.port))
    except:
        print 'cannot connect to root tablet'
        root_tablet.server.sock.close()
        root_tablet.server.sock = None
        return None

def get_root_tablet(master_addr,master_port):
    s = socket(AF_INET, SOCK_STREAM)
    try:
        s.connect((master_addr,master_port))
    except:
        print 'cannot connet to master server'
        s.close()
        s = None
        return None

    # program version
    pkt = pack('!I',1)
    send_packet(s,pkt,0,0)
    resp_buf = recv_packet(s)
    
    offset = 0
    
    err_code = unpack_from('!I',resp_buf,offset)
    offset += calcsize('!I')
    
    if err_code != 0:
        print 'response error'
        s.close()
        s = None
        return None
    
    root_tablet = unpack_tablet(resp_buf,offset)
    root_tablet.server.address = unpack_server_address(resp_buf,offset)

    return root_tablet

def usage():
    print '%s -a master_addr -p master_port -t table_name -s start_row [-e end_row] [--debug]' % sys.argv[0]

def main():
    
    if len(sys.argv)<7:
        usage()
        sys.exit(0)

    try:
        opts, args = getopt.getopt(sys.argv[1:], "a:p:t:s:e:", ["debug"])
    except getopt.GetoptError, err:
        print str(err)
        usage()
        sys.exit(2)

    master_addr = None
    master_port = None
    table_name = None
    start_row = None
    end_row = None
    debug_mode = False

    for o, a in opts:
        if o == '-a':
            master_addr = a
        elif o == '-p':
            master_port = a
        elif o == '-t':
            table_name = a
        elif o == '-s':
            start_row = a
        elif o == '-e':
            end_row = a
        elif o == '--debug':
            debug_mode = true
        else:
            usage()
            sys.exit(2)
            
    if master_addr == None:
        print 'no master address'
        usage()
        sys.exit(2)

    if master_port == None:
        print 'no master port'
        usage()
        sys.exit(2)
        
    if table_name == None:
        print 'no table name'
        usage()
        sys.exit(2)
        
    if start_row == None:
        print 'no start row'
        usage()
        sys.exit(2)
    
    # get root tablet
    root_tablet = None
    root_tablet = get_root_tablet(master_addr,master_port)
    if root_tablet == None:
        sys.exit(2)
        
    # get table meta data
    tablet_list = get_table_meta_data(root_tablet,table_name)
    if tablet_liet == None:
        sys.exit(2)

main()